/**
* jQuery ligerUI 1.3.3
*
* http://ligerui.com
*
* Author daomi 2015 [ gd_star@163.com ]
*
*/
(function ($) {
  $.fn.ligerTree = function (options) {
    return $.ligerui.run.call(this, 'ligerTree', arguments)
  }

  $.fn.ligerGetTreeManager = function () {
    return $.ligerui.run.call(this, 'ligerGetTreeManager', arguments)
  }

  $.ligerDefaults.Tree = {
    url: null,
    urlParms: null, // url带参数
    data: null,
    checkbox: true,
    autoCheckboxEven: true,
    enabledCompleteCheckbox: true, // 是否启用半选择
    parentIcon: 'folder',
    childIcon: 'leaf',
    textFieldName: 'text',
    attribute: ['id', 'url'],
    treeLine: true, // 是否显示line
    nodeWidth: 90,
    statusName: '__status',
    isLeaf: null, // 是否子节点的判断函数
    single: false, // 是否单选
    needCancel: true,			// 已选的是否需要取消操作
    onBeforeExpand: function () { },
    onContextmenu: function () { },
    onExpand: function () { },
    onBeforeCollapse: function () { },
    onCollapse: function () { },
    onBeforeSelect: function () { },
    onSelect: function () { },
    onBeforeCancelSelect: function () { },
    onCancelselect: function () { },
    onCheck: function () { },
    onSuccess: function () { },
    onError: function () { },
    onClick: function () { },
    idFieldName: 'id',
    parentIDFieldName: null,
    topParentIDValue: 0,
    onBeforeAppend: function () { }, // 加载数据前事件，可以通过return false取消操作
    onAppend: function () { }, // 加载数据时事件，对数据进行预处理以后
    onAfterAppend: function () { }, // 加载数据完事件
    slide: true, // 是否以动画的形式显示
    iconFieldName: 'icon',
    nodeDraggable: false, // 是否允许拖拽
    nodeDraggingRender: null,
    btnClickToToggleOnly: true, // 是否点击展开/收缩 按钮时才有效
    ajaxType: 'post',
    ajaxContentType: null,
    render: null, // 自定义函数
    selectable: null, // 可选择判断函数
    /*
        是否展开
            1,可以是true/false
            2,也可以是数字(层次)N 代表第1层到第N层都是展开的，其他收缩
            3,或者是判断函数 函数参数e(data,level) 返回true/false

        优先级没有节点数据的isexpand属性高,并没有delay属性高
        */
    isExpand: null,
    /*
        是否延迟加载
            1,可以是true/false
            2,也可以是数字(层次)N 代表第N层延迟加载
            3,或者是字符串(Url) 加载数据的远程地址
            4,如果是数组,代表这些层都延迟加载,如[1,2]代表第1、2层延迟加载
            5,再是函数(运行时动态获取延迟加载参数) 函数参数e(data,level),返回true/false或者{url:...,parms:...}

        优先级没有节点数据的delay属性高
        */
    delay: null,

    // id字段
    idField: null,
    // parent id字段，可用于线性数据转换为tree数据
    parentIDField: null,
	    iconClsFieldName: null
  }

  $.ligerui.controls.Tree = function (element, options) {
    $.ligerui.controls.Tree.base.constructor.call(this, element, options)
  }

  $.ligerui.controls.Tree.ligerExtend($.ligerui.core.UIComponent, {
    _init: function () {
      $.ligerui.controls.Tree.base._init.call(this)
      var g = this; var p = this.options
      if (p.single) p.autoCheckboxEven = false
    },
    _render: function () {
      var g = this; var p = this.options
      g.set(p, true)
      g.tree = $(g.element)
      g.tree.addClass('l-tree')
      g.toggleNodeCallbacks = []
      g.sysAttribute = ['isexpand', 'ischecked', 'href', 'style', 'delay']
      g.loading = $("<div class='l-tree-loading'></div>")
      g.tree.after(g.loading)
      g.data = []
      g.maxOutlineLevel = 1
      g.treedataindex = 0
      g._applyTree()
      g._setTreeEven()
      g.set(p, false)
    },
    _setTreeLine: function (value) {
      if (value) this.tree.removeClass('l-tree-noline')
      else this.tree.addClass('l-tree-noline')
    },
    _setParms: function () {
      var g = this; var p = this.options
      if ($.isFunction(p.parms)) p.parms = p.parms()
    },
    reload: function (callback) {
      var g = this; var p = this.options
      g.clear()
      g.loadData(null, p.url, null, {
        success: callback
      })
    },

    // 刷新节点
    reloadNode: function (node, data, callback) {
      var g = this; var p = this.options
      g.clear(node)
      if (typeof (data) === 'string') {
        g.loadData(node, data, null, {
          success: callback
        })
      } else {
        if (!data) return
        if (p.idField && p.parentIDField) {
          data = g.arrayToTree(data, p.idField, p.parentIDField)
        }
        g.append(node, data)
      }
    },
    _setUrl: function (url) {
      var g = this; var p = this.options
      if (url) {
        g.clear()
        g.loadData(null, url)
      }
    },
    _setData: function (data) {
      if (data) {
        this.clear()
        this.append(null, data)
      }
    },
    setData: function (data) {
      this.set('data', data)
    },
    getData: function () {
      return this.data
    },
    // 是否包含子节点
    hasChildren: function (treenodedata) {
      if (this.options.isLeaf) return !this.options.isLeaf(treenodedata)
      return !!treenodedata.children
    },
    // 获取父节点 数据
    getParent: function (treenode, level) {
      var g = this
      treenode = g.getNodeDom(treenode)
      var parentTreeNode = g.getParentTreeItem(treenode, level)
      if (!parentTreeNode) return null
      var parentIndex = $(parentTreeNode).attr('treedataindex')
      return g._getDataNodeByTreeDataIndex(g.data, parentIndex)
    },
    // 获取父节点
    getParentTreeItem: function (treenode, level) {
      var g = this
      treenode = g.getNodeDom(treenode)
      var treeitem = $(treenode)
      if (treeitem.parent().hasClass('l-tree')) { return null }
      if (level == undefined) {
        if (treeitem.parent().parent('li').length == 0) { return null }
        return treeitem.parent().parent('li')[0]
      }
      var currentLevel = parseInt(treeitem.attr('outlinelevel'))
      var currenttreeitem = treeitem
      for (var i = currentLevel - 1; i >= level; i--) {
        currenttreeitem = currenttreeitem.parent().parent('li')
      }
      return currenttreeitem[0]
    },
    getChecked: function () {
      var g = this; var p = this.options
      if (!this.options.checkbox) return null
      var nodes = []
      $('.l-checkbox-checked', g.tree).parent().parent('li').each(function () {
        var treedataindex = parseInt($(this).attr('treedataindex'))
        nodes.push({ target: this, data: g._getDataNodeByTreeDataIndex(g.data, treedataindex) })
      })
      return nodes
    },
    getCheckedData: function () {
      var g = this; var p = this.options
      if (!this.options.checkbox) return null
      var nodes = []
      $('.l-checkbox-checked', g.tree).parent().parent('li').each(function () {
        var treedataindex = parseInt($(this).attr('treedataindex'))
        nodes.push(g._getDataNodeByTreeDataIndex(g.data, treedataindex))
      })
      return nodes
    },

    // add by superzoc 12/24/2012
    refreshTree: function () {
      var g = this; var p = this.options
      $.each(this.getChecked(), function (k, v) {
        g._setParentCheckboxStatus($(v.target))
      })
    },
    getSelected: function () {
      var g = this; var p = this.options
      var node = {}
      node.target = $('.l-selected', g.tree).parent('li')[0]
      if (node.target) {
        var treedataindex = parseInt($(node.target).attr('treedataindex'))
        node.data = g._getDataNodeByTreeDataIndex(g.data, treedataindex)
        return node
      }
      return null
    },
    // 升级为父节点级别
    upgrade: function (treeNode) {
      var g = this; var p = this.options
      $('.l-note', treeNode).each(function () {
        $(this).removeClass('l-note').addClass('l-expandable-open')
      })
      $('.l-note-last', treeNode).each(function () {
        $(this).removeClass('l-note-last').addClass('l-expandable-open')
      })
      $('.' + g._getChildNodeClassName(), treeNode).each(function () {
        $(this)
          .removeClass(g._getChildNodeClassName())
          .addClass(g._getParentNodeClassName(true))
      })
    },
    // 降级为叶节点级别
    demotion: function (treeNode) {
      var g = this; var p = this.options
      if (!treeNode && treeNode[0].tagName.toLowerCase() != 'li') return
      var islast = $(treeNode).hasClass('l-last')
      $('.l-expandable-open', treeNode).each(function () {
        $(this).removeClass('l-expandable-open')
          .addClass(islast ? 'l-note-last' : 'l-note')
      })
      $('.l-expandable-close', treeNode).each(function () {
        $(this).removeClass('l-expandable-close')
          .addClass(islast ? 'l-note-last' : 'l-note')
      })
      $('.' + g._getParentNodeClassName(true), treeNode).each(function () {
        $(this)
          .removeClass(g._getParentNodeClassName(true))
          .addClass(g._getChildNodeClassName())
      })
    },
    collapseAll: function () {
      var g = this; var p = this.options
      $('.l-expandable-open', g.tree).click()
    },
    expandAll: function () {
      var g = this; var p = this.options
      $('.l-expandable-close', g.tree).click()
    },
    arrayToTree: function (data, id, pid) // 将ID、ParentID这种数据格式转换为树格式
    {
      var g = this; var p = this.options
      var childrenName = 'children'
      if (!data || !data.length) return []
      var targetData = [] // 存储数据的容器(返回)
      var records = {}
      var itemLength = data.length // 数据集合的个数
      for (var i = 0; i < itemLength; i++) {
        var o = data[i]
        var key = getKey(o[id])
        records[key] = o
      }
      for (var i = 0; i < itemLength; i++) {
        var currentData = data[i]
        var key = getKey(currentData[pid])
        var parentData = records[key]
        if (!parentData) {
          targetData.push(currentData)
          continue
        }
        parentData[childrenName] = parentData[childrenName] || []
        parentData[childrenName].push(currentData)
      }
      return targetData

      function getKey (key) {
        if (typeof (key) === 'string') key = key.replace(/[.]/g, '').toLowerCase()
        return key
      }
    },
    loadData: function (node, url, param, e) {
      var g = this; var p = this.options
      e = $.extend({
        showLoading: function () {
          g.loading.show()
        },
        success: function () { },
        error: function () { },
        hideLoading: function () {
          g.loading.hide()
        }
      }, e || {})
      var ajaxtype = p.ajaxType
      // 解决树无法设置parms的问题
      param = $.extend(($.isFunction(p.parms) ? p.parms() : p.parms), param)
      if (p.ajaxContentType == 'application/json' && typeof (param) !== 'string') {
        param = liger.toJSON(param)
      }
      var urlParms = $.isFunction(p.urlParms) ? p.urlParms.call(g) : p.urlParms
      if (urlParms) {
        for (name in urlParms) {
          url += url.indexOf('?') == -1 ? '?' : '&'
          url += name + '=' + urlParms[name]
        }
      }
      var ajaxOp = {
        type: ajaxtype,
        url: url,
        data: param,
        dataType: 'json',
        beforeSend: function () {
          e.showLoading()
        },
        success: function (data) {
          if (!data) return
          if (p.idField && p.parentIDField) {
            data = g.arrayToTree(data, p.idField, p.parentIDField)
          }
          e.hideLoading()
          g.append(node, data)
          g.trigger('success', [data])
          e.success(data)
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
          try {
            e.hideLoading()
            g.trigger('error', [XMLHttpRequest, textStatus, errorThrown])
            e.error(XMLHttpRequest, textStatus, errorThrown)
          } catch (e) {

          }
        }
      }
      if (p.ajaxContentType) {
        ajaxOp.contentType = p.ajaxContentType
      }
      $.ajax(ajaxOp)
    },

    // 清空
    clear: function (node) {
      var g = this; var p = this.options
      if (!node) {
        g.toggleNodeCallbacks = []
        g.data = null
        g.data = []
        g.nodes = null
        g.tree.html('')
      } else {
        var nodeDom = g.getNodeDom(node)
        var nodeData = g._getDataNodeByTreeDataIndex(g.data, $(nodeDom).attr('treedataindex'))
        $(nodeDom).find('ul.l-children').remove()
        if (nodeData) nodeData.children = []
      }
    },

    // parm [treeNode] dom节点(li)、节点数据 或者节点 dataindex
    getNodeDom: function (nodeParm) {
      var g = this; var p = this.options
      if (nodeParm == null) return nodeParm
      if (typeof (nodeParm) === 'string' || typeof (nodeParm) === 'number') {
        return $('li[treedataindex=' + nodeParm + ']', g.tree).get(0)
      } else if (typeof (nodeParm) === 'object' && 'treedataindex' in nodeParm) // nodedata
      {
        return g.getNodeDom(nodeParm.treedataindex)
      } else if (nodeParm.target && nodeParm.data) {
        return nodeParm.target
      }
      return nodeParm
    },
    hide: function (treeNode) {
      var g = this; var p = this.options
      treeNode = g.getNodeDom(treeNode)
      if (treeNode) $(treeNode).hide()
    },
    show: function (treeNode) {
      var g = this; var p = this.options
      treeNode = g.getNodeDom(treeNode)
      if (treeNode) $(treeNode).show()
    },
    // parm [treeNode] dom节点(li)、节点数据 或者节点 dataindex
    remove: function (treeNode) {
      var g = this; var p = this.options
      treeNode = g.getNodeDom(treeNode)
      var treedataindex = parseInt($(treeNode).attr('treedataindex'))
      var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex)
      if (treenodedata) g._setTreeDataStatus([treenodedata], 'delete')
      var parentNode = g.getParentTreeItem(treeNode)
      // 复选框处理
      if (p.checkbox) {
        g._setParentCheckboxStatus($(treeNode))
      }
      $(treeNode).remove()
      g._updateStyle(parentNode ? $('ul:first', parentNode) : g.tree)
    },
    _updateStyle: function (ul) {
      var g = this; var p = this.options
      var itmes = $(' > li', ul)
      var treeitemlength = itmes.length
      if (!treeitemlength) return
      // 遍历设置子节点的样式
      itmes.each(function (i, item) {
        if (i == 0 && !$(this).hasClass('l-first')) { $(this).addClass('l-first') }
        if (i == treeitemlength - 1 && !$(this).hasClass('l-last')) { $(this).addClass('l-last') }
        if (i == 0 && i == treeitemlength - 1) { $(this).addClass('l-onlychild') }
        $('> div .l-note,> div .l-note-last', this)
          .removeClass('l-note l-note-last')
          .addClass(i == treeitemlength - 1 ? 'l-note-last' : 'l-note')
        g._setTreeItem(this, { isLast: i == treeitemlength - 1 })
      })
    },
    // parm [domnode] dom节点(li)、节点数据 或者节点 dataindex
    update: function (domnode, newnodedata) {
      var g = this; var p = this.options
      domnode = g.getNodeDom(domnode)
      var treedataindex = parseInt($(domnode).attr('treedataindex'))
      nodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex)
      for (var attr in newnodedata) {
        nodedata[attr] = newnodedata[attr]
        if (attr == p.textFieldName) {
          $('> .l-body > span', domnode).text(newnodedata[attr])
        }
      }
    },
    // 增加节点集合
    // parm [newdata] 数据集合 Array
    // parm [parentNode] dom节点(li)、节点数据 或者节点 dataindex
    // parm [nearNode] 附加到节点的上方/下方(非必填)
    // parm [isAfter] 附加到节点的下方(非必填)
    append: function (parentNode, newdata, nearNode, isAfter) {
      var g = this; var p = this.options
      parentNode = g.getNodeDom(parentNode)
      if (g.trigger('beforeAppend', [parentNode, newdata]) == false) return false
      if (!newdata || !newdata.length) return false
      if (p.idFieldName && p.parentIDFieldName) { newdata = g.arrayToTree(newdata, p.idFieldName, p.parentIDFieldName) }
      g._addTreeDataIndexToData(newdata)
      g._setTreeDataStatus(newdata, 'add')
      if (nearNode != null) {
        nearNode = g.getNodeDom(nearNode)
      }
      g.trigger('append', [parentNode, newdata])
      g._appendData(parentNode, newdata)
      if (parentNode == null)// 增加到根节点
      {
        var gridhtmlarr = g._getTreeHTMLByData(newdata, 1, [], true)
        gridhtmlarr[gridhtmlarr.length - 1] = gridhtmlarr[0] = ''
        if (nearNode != null) {
          $(nearNode)[isAfter ? 'after' : 'before'](gridhtmlarr.join(''))
          g._updateStyle(parentNode ? $('ul:first', parentNode) : g.tree)
        } else {
          // remove last node class
          if ($('> li:last', g.tree).length > 0) { g._setTreeItem($('> li:last', g.tree)[0], { isLast: false }) }
          g.tree.append(gridhtmlarr.join(''))
        }
        $('.l-body', g.tree).hover(function () {
          $(this).addClass('l-over')
        }, function () {
          $(this).removeClass('l-over')
        })
        g._upadteTreeWidth()
        g.trigger('afterAppend', [parentNode, newdata])
        return
      }
      var treeitem = $(parentNode)
      var outlineLevel = parseInt(treeitem.attr('outlinelevel'))

      var hasChildren = $('> ul', treeitem).length > 0
      if (!hasChildren) {
        treeitem.append("<ul class='l-children'></ul>")
        // 设置为父节点
        g.upgrade(parentNode)
      }
      var isLast = []
      for (var i = 1; i <= outlineLevel - 1; i++) {
        var currentParentTreeItem = $(g.getParentTreeItem(parentNode, i))
        isLast.push(currentParentTreeItem.hasClass('l-last'))
      }
      isLast.push(treeitem.hasClass('l-last'))
      var gridhtmlarr = g._getTreeHTMLByData(newdata, outlineLevel + 1, isLast, true)
      gridhtmlarr[gridhtmlarr.length - 1] = gridhtmlarr[0] = ''
      if (nearNode != null) {
        $(nearNode)[isAfter ? 'after' : 'before'](gridhtmlarr.join(''))
        g._updateStyle(parentNode ? $('ul:first', parentNode) : g.tree)
      } else {
        // remove last node class
        if ($('> .l-children > li:last', treeitem).length > 0) { g._setTreeItem($('> .l-children > li:last', treeitem)[0], { isLast: false }) }
        $('>.l-children', parentNode).append(gridhtmlarr.join(''))
      }
      g._upadteTreeWidth()
      $('>.l-children .l-body', parentNode).hover(function () {
        $(this).addClass('l-over')
      }, function () {
        $(this).removeClass('l-over')
      })
      g.trigger('afterAppend', [parentNode, newdata])
    },
    // parm [nodeParm] dom节点(li)、节点数据 或者节点 dataindex
    cancelSelect: function (nodeParm, isTriggerEvent) {
      var g = this; var p = this.options
      var domNode = g.getNodeDom(nodeParm)
      var treeitem = $(domNode)
      var treedataindex = parseInt(treeitem.attr('treedataindex'))
      var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex)
      var treeitembody = $('>div:first', treeitem)
      if (p.checkbox) { $('.l-checkbox', treeitembody).removeClass('l-checkbox-checked').addClass('l-checkbox-unchecked') } else { treeitembody.removeClass('l-selected') }
      if (isTriggerEvent != false) {
        g.trigger('cancelSelect', [{ data: treenodedata, target: treeitem[0] }])
      }
    },
    // 选择节点(参数：条件函数、Dom节点或ID值)
    selectNode: function (selectNodeParm, isTriggerEvent) {
      var g = this; var p = this.options
      var clause = null
      if (typeof (selectNodeParm) === 'function') {
        clause = selectNodeParm
      } else if (typeof (selectNodeParm) === 'object') {
        var treeitem = $(selectNodeParm)
        var treedataindex = parseInt(treeitem.attr('treedataindex'))
        var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex)
        var treeitembody = $('>div:first', treeitem)
        if (!treeitembody.length) {
          treeitembody = $('li[treedataindex=' + treedataindex + '] >div:first', g.tree)
        }
        if (p.checkbox) {
          $('.l-checkbox', treeitembody).removeClass('l-checkbox-unchecked').addClass('l-checkbox-checked')
        } else {
          $('div.l-selected', g.tree).removeClass('l-selected')
          treeitembody.addClass('l-selected')
        }
        if (isTriggerEvent != false) {
          g.trigger('select', [{ data: treenodedata, target: treeitembody.parent().get(0) }])
        }
        return
      } else {
        clause = function (data) {
          if (!data[p.idFieldName] && data[p.idFieldName] != 0) return false
          return strTrim(data[p.idFieldName].toString()) == strTrim(selectNodeParm.toString())
        }
      }
      $('li', g.tree).each(function () {
        var treeitem = $(this)
        var treedataindex = parseInt(treeitem.attr('treedataindex'))
        var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex)
        if (clause(treenodedata, treedataindex)) {
          g.selectNode(this, isTriggerEvent)
        } else {
          // 修复多选checkbox为true时调用该方法会取消已经选中节点的问题
          if (!g.options.checkbox) {
            g.cancelSelect(this, isTriggerEvent)
          }
        }
      })
    },
    getTextByID: function (id) {
      var g = this; var p = this.options
      var data = g.getDataByID(id)
      if (!data) return null
      return data[p.textFieldName]
    },
    getDataByID: function (id) {
      var g = this; var p = this.options
      var data = null

      if (g.data && g.data.length) {
        return find(g.data)
      }

      function find (items) {
        for (var i = 0; i < items.length; i++) {
          var dataItem = items[i]
          if (dataItem[p.idFieldName] == id) return dataItem
          if (dataItem.children && dataItem.children.length) {
            var o = find(dataItem.children)
            if (o) return o
          }
        }
        return null
      }

      $('li', g.tree).each(function () {
        if (data) return
        var treeitem = $(this)
        var treedataindex = parseInt(treeitem.attr('treedataindex'))
        var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex)
        if (treenodedata[p.idFieldName].toString() == id.toString()) {
          data = treenodedata
        }
      })
      return data
    },
    arrayToTree: function (data, id, pid) // 将ID、ParentID这种数据格式转换为树格式
    {
      if (!data || !data.length) return []
      var targetData = [] // 存储数据的容器(返回)
      var records = {}
      var itemLength = data.length // 数据集合的个数
      for (var i = 0; i < itemLength; i++) {
        var o = data[i]
        records[o[id]] = o
      }
      for (var i = 0; i < itemLength; i++) {
        var currentData = data[i]
        var parentData = records[currentData[pid]]
        if (!parentData) {
          targetData.push(currentData)
          continue
        }
        parentData.children = parentData.children || []
        parentData.children.push(currentData)
      }
      return targetData
    },

    // 根据数据索引获取数据
    _getDataNodeByTreeDataIndex: function (data, treedataindex) {
      var g = this; var p = this.options
      for (var i = 0; i < data.length; i++) {
        if (data[i].treedataindex == treedataindex) { return data[i] }
        if (data[i].children) {
          var targetData = g._getDataNodeByTreeDataIndex(data[i].children, treedataindex)
          if (targetData) return targetData
        }
      }
      return null
    },
    // 设置数据状态
    _setTreeDataStatus: function (data, status) {
      var g = this; var p = this.options
      $(data).each(function () {
        this[p.statusName] = status
        if (this.children) {
          g._setTreeDataStatus(this.children, status)
        }
      })
    },
    // 设置data 索引
    _addTreeDataIndexToData: function (data) {
      var g = this; var p = this.options
      $(data).each(function () {
        if (this.treedataindex != undefined) return
        this.treedataindex = g.treedataindex++
        if (this.children) {
          g._addTreeDataIndexToData(this.children)
        }
      })
    },
    _addToNodes: function (data) {
      var g = this; var p = this.options
      g.nodes = g.nodes || []
      g.nodes.push(data)
      if (!data.children) return
      $(data.children).each(function (i, item) {
        g._addToNodes(item)
      })
    },
    // 添加项到g.data
    _appendData: function (treeNode, data) {
      var g = this; var p = this.options
      var treedataindex = parseInt($(treeNode).attr('treedataindex'))
      var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex)
      if (g.treedataindex == undefined) g.treedataindex = 0
      if (treenodedata && treenodedata.children == undefined) treenodedata.children = []
      $(data).each(function (i, item) {
        if (treenodedata) { treenodedata.children[treenodedata.children.length] = item } else { g.data[g.data.length] = item }
        g._addToNodes(item)
      })
    },
    _setTreeItem: function (treeNode, options) {
      var g = this; var p = this.options
      if (!options) return
      treeNode = g.getNodeDom(treeNode)
      var treeItem = $(treeNode)
      var outlineLevel = parseInt(treeItem.attr('outlinelevel'))
      if (options.isLast != undefined) {
        if (options.isLast == true) {
          treeItem.removeClass('l-last').addClass('l-last')
          $('> div .l-note', treeItem).removeClass('l-note').addClass('l-note-last')
          $('.l-children li', treeItem)
            .find('.l-box:eq(' + (outlineLevel - 1) + ')')
            .removeClass('l-line')
        } else if (options.isLast == false) {
          treeItem.removeClass('l-last')
          $('> div .l-note-last', treeItem).removeClass('l-note-last').addClass('l-note')

          $('.l-children li', treeItem)
            .find('.l-box:eq(' + (outlineLevel - 1) + ')')
            .removeClass('l-line')
            .addClass('l-line')
        }
      }
    },
    _upadteTreeWidth: function () {
      var g = this; var p = this.options
      var treeWidth = g.maxOutlineLevel * 22
      if (p.checkbox) treeWidth += 22
      if (p.parentIcon || p.childIcon) treeWidth += 22
      treeWidth += p.nodeWidth
      g.tree.width(treeWidth)
    },
    _getChildNodeClassName: function () {
      var g = this; var p = this.options
      return 'l-tree-icon-' + p.childIcon
    },
    _getParentNodeClassName: function (isOpen) {
      var g = this; var p = this.options
      var nodeclassname = 'l-tree-icon-' + p.parentIcon
      if (isOpen) nodeclassname += '-open'
      return nodeclassname
    },
    // 判断节点是否展开状态,返回true/false
    _isExpand: function (o, level) {
      var g = this; var p = this.options
      var isExpand = o.isExpand != null ? o.isExpand : (o.isexpand != null ? o.isexpand : p.isExpand)
      if (isExpand == null) return true
      if (typeof (isExpand) === 'function') isExpand = p.isExpand({ data: o, level: level })
      if (typeof (isExpand) === 'boolean') return isExpand
      if (typeof (isExpand) === 'string') return isExpand == 'true'
      if (typeof (isExpand) === 'number') return isExpand > level
      return true
    },
    // 获取节点的延迟加载状态,返回true/false (本地模式) 或者是object({url :'...',parms:null})(远程模式)
    _getDelay: function (o, level) {
      var g = this; var p = this.options
      var delay = o.delay != null ? o.delay : p.delay
      if (delay == null) return false
      if (typeof (delay) === 'function') delay = delay({ data: o, level: level })
      if (typeof (delay) === 'boolean') return delay
      if (typeof (delay) === 'string') return { url: delay }
      if (typeof (delay) === 'number') delay = [delay]
      if ($.isArray(delay)) return $.inArray(level, delay) != -1
      if (typeof (delay) === 'object' && delay.url) return delay
      return false
    },
    // 根据data生成最终完整的tree html
    _getTreeHTMLByData: function (data, outlineLevel, isLast, isExpand) {
      var g = this; var p = this.options
      if (g.maxOutlineLevel < outlineLevel) { g.maxOutlineLevel = outlineLevel }
      isLast = isLast || []
      outlineLevel = outlineLevel || 1
      var treehtmlarr = []
      if (!isExpand) treehtmlarr.push('<ul class="l-children" style="display:none">')
      else treehtmlarr.push("<ul class='l-children'>")
      for (var i = 0; i < data.length; i++) {
        var o = data[i]
        var isFirst = i == 0
        var isLastCurrent = i == data.length - 1
        var delay = g._getDelay(o, outlineLevel)
        var isExpandCurrent = delay ? false : g._isExpand(o, outlineLevel)

        treehtmlarr.push('<li ')
        if (o.treedataindex != undefined) { treehtmlarr.push('treedataindex="' + o.treedataindex + '" ') }
        if (isExpandCurrent) { treehtmlarr.push('isexpand=' + o.isexpand + ' ') }
        treehtmlarr.push('outlinelevel=' + outlineLevel + ' ')
        // 增加属性支持
        for (var j = 0; j < g.sysAttribute.length; j++) {
          if ($(this).attr(g.sysAttribute[j])) { data[dataindex][g.sysAttribute[j]] = $(this).attr(g.sysAttribute[j]) }
        }
        for (var j = 0; j < p.attribute.length; j++) {
          if (o[p.attribute[j]]) { treehtmlarr.push(p.attribute[j] + '="' + o[p.attribute[j]] + '" ') }
        }

        // css class
        treehtmlarr.push('class="')
        isFirst && treehtmlarr.push('l-first ')
        isLastCurrent && treehtmlarr.push('l-last ')
        isFirst && isLastCurrent && treehtmlarr.push('l-onlychild ')
        treehtmlarr.push('"')
        treehtmlarr.push('>')
        treehtmlarr.push('<div class="l-body')
        if (p.selectable && p.selectable(o) == false) {
          treehtmlarr.push(' l-unselectable')
        }
        treehtmlarr.push('">')
        for (var k = 0; k <= outlineLevel - 2; k++) {
          if (isLast[k]) treehtmlarr.push('<div class="l-box"></div>')
          else treehtmlarr.push('<div class="l-box l-line"></div>')
        }
        if (g.hasChildren(o)) {
          if (isExpandCurrent) treehtmlarr.push('<div class="l-box l-expandable-open"></div>')
          else treehtmlarr.push('<div class="l-box l-expandable-close"></div>')
          if (p.checkbox) {
            if (o.ischecked) { treehtmlarr.push('<div class="l-box l-checkbox l-checkbox-checked"></div>') } else { treehtmlarr.push('<div class="l-box l-checkbox l-checkbox-unchecked"></div>') }
          }
          if (p.parentIcon) {
            // node icon
            treehtmlarr.push('<div class="l-box l-tree-icon ')
            treehtmlarr.push(g._getParentNodeClassName(!!isExpandCurrent) + ' ')
            if (p.iconFieldName && o[p.iconFieldName]) { treehtmlarr.push('l-tree-icon-none') } else if (p.iconClsFieldName && o[p.iconClsFieldName]) { treehtmlarr.push('l-tree-icon-' + o[p.iconClsFieldName] + ' ') }
            treehtmlarr.push('">')
            if (p.iconFieldName && o[p.iconFieldName]) { treehtmlarr.push('<img src="' + o[p.iconFieldName] + '" />') }
            treehtmlarr.push('</div>')
          }
        } else {
          if (isLastCurrent) treehtmlarr.push('<div class="l-box l-note-last"></div>')
          else treehtmlarr.push('<div class="l-box l-note"></div>')
          if (p.checkbox) {
            if (o.ischecked) { treehtmlarr.push('<div class="l-box l-checkbox l-checkbox-checked"></div>') } else { treehtmlarr.push('<div class="l-box l-checkbox l-checkbox-unchecked"></div>') }
          }
          if (p.childIcon) {
            // node icon
            treehtmlarr.push('<div class="l-box l-tree-icon ')
            treehtmlarr.push(g._getChildNodeClassName() + ' ')
            if (p.iconFieldName && o[p.iconFieldName]) { treehtmlarr.push('l-tree-icon-none') } else if (p.iconClsFieldName && o[p.iconClsFieldName]) { treehtmlarr.push('l-tree-icon-' + o[p.iconClsFieldName] + ' ') }

            treehtmlarr.push('">')
            if (p.iconFieldName && o[p.iconFieldName]) { treehtmlarr.push('<img src="' + o[p.iconFieldName] + '" />') }
            treehtmlarr.push('</div>')
          }
        }
        if (p.render) {
          treehtmlarr.push('<span>' + p.render(o, o[p.textFieldName]) + '</span>')
        } else {
          treehtmlarr.push('<span>' + o[p.textFieldName] + '</span>')
        }
        treehtmlarr.push('</div>')
        if (g.hasChildren(o)) {
          var isLastNew = []
          for (var k = 0; k < isLast.length; k++) {
            isLastNew.push(isLast[k])
          }
          isLastNew.push(isLastCurrent)
          if (delay) {
            if (delay == true) {
              g.toggleNodeCallbacks.push({
                data: o,
                callback: function (dom, o) {
                  var content = g._getTreeHTMLByData(o.children, outlineLevel + 1, isLastNew, isExpandCurrent).join('')
                  $(dom).append(content)
                  $('>.l-children .l-body', dom).hover(function () {
                    $(this).addClass('l-over')
                  }, function () {
                    $(this).removeClass('l-over')
                  })
                  g._removeToggleNodeCallback(o)
                }
              })
            } else if (delay.url) {
              (function (o, url, parms) {
                g.toggleNodeCallbacks.push({
                  data: o,
                  callback: function (dom, o) {
                    g.loadData(dom, url, parms, {
                      showLoading: function () {
                        $('div.l-expandable-close:first', dom).addClass('l-box-loading')
                      },
                      hideLoading: function () {
                        $('div.l-box-loading:first', dom).removeClass('l-box-loading')
                      }
                    })
                    g._removeToggleNodeCallback(o)
                  }
                })
              })(o, delay.url, delay.parms)
            }
          } else {
            treehtmlarr.push(g._getTreeHTMLByData(o.children, outlineLevel + 1, isLastNew, isExpandCurrent).join(''))
          }
        }
        treehtmlarr.push('</li>')
      }
      treehtmlarr.push('</ul>')
      return treehtmlarr
    },
    _removeToggleNodeCallback: function (nodeData) {
      var g = this; var p = this.options
      for (var i = 0; i <= g.toggleNodeCallbacks.length; i++) {
        if (g.toggleNodeCallbacks[i] && g.toggleNodeCallbacks[i].data == nodeData) {
          g.toggleNodeCallbacks.splice(i, 1)
          break
        }
      }
    },
    // 根据简洁的html获取data
    _getDataByTreeHTML: function (treeDom) {
      var g = this; var p = this.options
      var data = []
      $('> li', treeDom).each(function (i, item) {
        var dataindex = data.length
        data[dataindex] =
                        {
                          treedataindex: g.treedataindex++
                        }
        data[dataindex][p.textFieldName] = $('> span,> a', this).html()
        for (var j = 0; j < g.sysAttribute.length; j++) {
          if ($(this).attr(g.sysAttribute[j])) { data[dataindex][g.sysAttribute[j]] = $(this).attr(g.sysAttribute[j]) }
        }
        for (var j = 0; j < p.attribute.length; j++) {
          if ($(this).attr(p.attribute[j])) { data[dataindex][p.attribute[j]] = $(this).attr(p.attribute[j]) }
        }
        if ($('> ul', this).length > 0) {
          data[dataindex].children = g._getDataByTreeHTML($('> ul', this))
        }
      })
      return data
    },
    _applyTree: function () {
      var g = this; var p = this.options
      g.data = g._getDataByTreeHTML(g.tree)
      var gridhtmlarr = g._getTreeHTMLByData(g.data, 1, [], true)
      gridhtmlarr[gridhtmlarr.length - 1] = gridhtmlarr[0] = ''
      g.tree.html(gridhtmlarr.join(''))
      g._upadteTreeWidth()
      $('.l-body', g.tree).hover(function () {
        $(this).addClass('l-over')
      }, function () {
        $(this).removeClass('l-over')
      })
    },
    _getSrcElementByEvent: function (e) {
      var g = this
      var obj = (e.target || e.srcElement)
      var tag = obj.tagName.toLowerCase()
      var jobjs = $(obj).parents().add(obj)
      var fn = function (parm) {
        for (var i = jobjs.length - 1; i >= 0; i--) {
          if ($(jobjs[i]).hasClass(parm)) return jobjs[i]
        }
        return null
      }
      if (jobjs.index(this.element) == -1) return { out: true }
      var r = {
        tree: fn('l-tree'),
        node: fn('l-body'),
        checkbox: fn('l-checkbox'),
        icon: fn('l-tree-icon'),
        text: tag == 'span'
      }
      if (r.node) {
        var treedataindex = parseInt($(r.node).parent().attr('treedataindex'))
        r.data = g._getDataNodeByTreeDataIndex(g.data, treedataindex)
      }
      return r
    },
    _setTreeEven: function () {
      var g = this; var p = this.options
      if (g.hasBind('contextmenu')) {
        g.tree.bind('contextmenu', function (e) {
          var obj = (e.target || e.srcElement)
          var treeitem = null
          if (obj.tagName.toLowerCase() == 'a' || obj.tagName.toLowerCase() == 'span' || $(obj).hasClass('l-box')) { treeitem = $(obj).parent().parent() } else if ($(obj).hasClass('l-body')) { treeitem = $(obj).parent() } else if (obj.tagName.toLowerCase() == 'li') { treeitem = $(obj) }
          if (!treeitem) return
          var treedataindex = parseInt(treeitem.attr('treedataindex'))
          var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex)
          return g.trigger('contextmenu', [{ data: treenodedata, target: treeitem[0] }, e])
        })
      }
      g.tree.click(function (e) {
        var obj = (e.target || e.srcElement)
        var treeitem = null
        if (obj.tagName.toLowerCase() == 'a' || obj.tagName.toLowerCase() == 'span' || $(obj).hasClass('l-box')) { treeitem = $(obj).parent().parent() } else if ($(obj).hasClass('l-body')) { treeitem = $(obj).parent() } else { treeitem = $(obj) }
        if (!treeitem) return
        var treedataindex = parseInt(treeitem.attr('treedataindex'))
        var treenodedata = g._getDataNodeByTreeDataIndex(g.data, treedataindex)
        var treeitembtn = $('div.l-body:first', treeitem).find('div.l-expandable-open:first,div.l-expandable-close:first')
        var clickOnTreeItemBtn = $(obj).hasClass('l-expandable-open') || $(obj).hasClass('l-expandable-close')
        if (!$(obj).hasClass('l-checkbox') && !clickOnTreeItemBtn) {
          if (!treeitem.hasClass('l-unselectable')) {
            if ($('>div:first', treeitem).hasClass('l-selected') && p.needCancel) {
              if (g.trigger('beforeCancelSelect', [{ data: treenodedata, target: treeitem[0] }]) == false) { return false }

              $('>div:first', treeitem).removeClass('l-selected')
              g.trigger('cancelSelect', [{ data: treenodedata, target: treeitem[0] }])
            } else {
              if (g.trigger('beforeSelect', [{ data: treenodedata, target: treeitem[0] }]) == false) { return false }
              $('.l-body', g.tree).removeClass('l-selected')
              $('>div:first', treeitem).addClass('l-selected')
              g.trigger('select', [{ data: treenodedata, target: treeitem[0] }])
            }
          }
        }
        // chekcbox even
        if ($(obj).hasClass('l-checkbox')) {
          if (p.autoCheckboxEven) {
            // 状态：未选中
            if ($(obj).hasClass('l-checkbox-unchecked')) {
              $(obj).removeClass('l-checkbox-unchecked').addClass('l-checkbox-checked')
              $('.l-children .l-checkbox', treeitem)
                .removeClass('l-checkbox-incomplete l-checkbox-unchecked')
                .addClass('l-checkbox-checked')
              g.trigger('check', [{ data: treenodedata, target: treeitem[0] }, true])
            }
            // 状态：选中
            else if ($(obj).hasClass('l-checkbox-checked')) {
              $(obj).removeClass('l-checkbox-checked').addClass('l-checkbox-unchecked')
              $('.l-children .l-checkbox', treeitem)
                .removeClass('l-checkbox-incomplete l-checkbox-checked')
                .addClass('l-checkbox-unchecked')
              g.trigger('check', [{ data: treenodedata, target: treeitem[0] }, false])
            }
            // 状态：未完全选中
            else if ($(obj).hasClass('l-checkbox-incomplete')) {
              $(obj).removeClass('l-checkbox-incomplete').addClass('l-checkbox-checked')
              $('.l-children .l-checkbox', treeitem)
                .removeClass('l-checkbox-incomplete l-checkbox-unchecked')
                .addClass('l-checkbox-checked')
              g.trigger('check', [{ data: treenodedata, target: treeitem[0] }, true])
            }
            g._setParentCheckboxStatus(treeitem)
          } else {
            // 状态：未选中
            if ($(obj).hasClass('l-checkbox-unchecked')) {
              $(obj).removeClass('l-checkbox-unchecked').addClass('l-checkbox-checked')
              // 是否单选
              if (p.single) {
                $('.l-checkbox', g.tree).not(obj).removeClass('l-checkbox-checked').addClass('l-checkbox-unchecked')
              }
              g.trigger('check', [{ data: treenodedata, target: treeitem[0] }, true])
            }
            // 状态：选中
            else if ($(obj).hasClass('l-checkbox-checked')) {
              $(obj).removeClass('l-checkbox-checked').addClass('l-checkbox-unchecked')
              g.trigger('check', [{ data: treenodedata, target: treeitem[0] }, false])
            }
          }
        }
        // 状态：已经张开
        else if (treeitembtn.hasClass('l-expandable-open') && (!p.btnClickToToggleOnly || clickOnTreeItemBtn)) {
          if (g.trigger('beforeCollapse', [{ data: treenodedata, target: treeitem[0] }]) == false) { return false }
          treeitembtn.removeClass('l-expandable-open').addClass('l-expandable-close')
          if (p.slide) { $('> .l-children', treeitem).slideToggle('fast') } else { $('> .l-children', treeitem).hide() }
          $('> div .' + g._getParentNodeClassName(true), treeitem)
            .removeClass(g._getParentNodeClassName(true))
            .addClass(g._getParentNodeClassName())
          g.trigger('collapse', [{ data: treenodedata, target: treeitem[0] }])
        }
        // 状态：没有张开
        else if (treeitembtn.hasClass('l-expandable-close') && (!p.btnClickToToggleOnly || clickOnTreeItemBtn)) {
          if (g.trigger('beforeExpand', [{ data: treenodedata, target: treeitem[0] }]) == false) { return false }

          $(g.toggleNodeCallbacks).each(function () {
            if (this.data == treenodedata) {
              this.callback(treeitem[0], treenodedata)
            }
          })
          treeitembtn.removeClass('l-expandable-close').addClass('l-expandable-open')
          var callback = function () {
            g.trigger('expand', [{ data: treenodedata, target: treeitem[0] }])
          }
          if (p.slide) {
            $('> .l-children', treeitem).slideToggle('fast', callback)
          } else {
            $('> .l-children', treeitem).show()
            callback()
          }
          $('> div .' + g._getParentNodeClassName(), treeitem)
            .removeClass(g._getParentNodeClassName())
            .addClass(g._getParentNodeClassName(true))
        }
        g.trigger('click', [{ data: treenodedata, target: treeitem[0] }])
      })

      // 节点拖拽支持
      if ($.fn.ligerDrag && p.nodeDraggable) {
        g.nodeDroptip = $("<div class='l-drag-nodedroptip' style='display:none'></div>").appendTo('body')
        g.tree.ligerDrag({
          revert: true,
          animate: false,
          proxyX: 20,
          proxyY: 20,
          proxy: function (draggable, e) {
            var src = g._getSrcElementByEvent(e)
            if (src.node) {
              var content = 'dragging'
              if (p.nodeDraggingRender) {
                content = p.nodeDraggingRender(draggable.draggingNodes, draggable, g)
              } else {
                content = ''
                var appended = false
                for (var i in draggable.draggingNodes) {
                  var node = draggable.draggingNodes[i]
                  if (appended) content += ','
                  content += node.text
                  appended = true
                }
              }
              var proxy = $("<div class='l-drag-proxy' style='display:none'><div class='l-drop-icon l-drop-no'></div>" + content + '</div>').appendTo('body')
              return proxy
            }
          },
          onRevert: function () { return false },
          onRendered: function () {
            this.set('cursor', 'default')
            g.children[this.id] = this
          },
          onStartDrag: function (current, e) {
            if (e.button == 2) return false
            this.set('cursor', 'default')
            var src = g._getSrcElementByEvent(e)
            if (src.checkbox) return false
            if (p.checkbox) {
              var checked = g.getChecked()
              this.draggingNodes = []
              for (var i in checked) {
                this.draggingNodes.push(checked[i].data)
              }
              if (!this.draggingNodes || !this.draggingNodes.length) return false
            } else {
              this.draggingNodes = [src.data]
            }
            this.draggingNode = src.data
            this.set('cursor', 'move')
            g.nodedragging = true
            this.validRange = {
              top: g.tree.offset().top,
              bottom: g.tree.offset().top + g.tree.height(),
              left: g.tree.offset().left,
              right: g.tree.offset().left + g.tree.width()
            }
          },
          onDrag: function (current, e) {
            var nodedata = this.draggingNode
            if (!nodedata) return false
            var nodes = this.draggingNodes ? this.draggingNodes : [nodedata]
            if (g.nodeDropIn == null) g.nodeDropIn = -1
            var pageX = e.pageX
            var pageY = e.pageY
            var visit = false
            var validRange = this.validRange
            if (pageX < validRange.left || pageX > validRange.right ||
                            pageY > validRange.bottom || pageY < validRange.top) {
              g.nodeDropIn = -1
              g.nodeDroptip.hide()
              this.proxy.find('.l-drop-icon:first').removeClass('l-drop-yes l-drop-add').addClass('l-drop-no')
              return
            }
            for (var i = 0, l = g.nodes.length; i < l; i++) {
              var nd = g.nodes[i]
              var treedataindex = nd.treedataindex
              if (nodedata.treedataindex == treedataindex) visit = true
              if ($.inArray(nd, nodes) != -1) continue
              var isAfter = !!visit
              if (g.nodeDropIn != -1 && g.nodeDropIn != treedataindex) continue
              var jnode = $('li[treedataindex=' + treedataindex + '] div:first', g.tree)
              var offset = jnode.offset()
              var range = {
                top: offset.top,
                bottom: offset.top + jnode.height(),
                left: g.tree.offset().left,
                right: g.tree.offset().left + g.tree.width()
              }
              if (pageX > range.left && pageX < range.right && pageY > range.top && pageY < range.bottom) {
                var lineTop = offset.top
                if (isAfter) lineTop += jnode.height()
                g.nodeDroptip.css({
                  left: range.left,
                  top: lineTop,
                  width: range.right - range.left
                }).show()
                g.nodeDropIn = treedataindex
                g.nodeDropDir = isAfter ? 'bottom' : 'top'
                if (pageY > range.top + 7 && pageY < range.bottom - 7) {
                  this.proxy.find('.l-drop-icon:first').removeClass('l-drop-no l-drop-yes').addClass('l-drop-add')
                  g.nodeDroptip.hide()
                  g.nodeDropInParent = true
                } else {
                  this.proxy.find('.l-drop-icon:first').removeClass('l-drop-no l-drop-add').addClass('l-drop-yes')
                  g.nodeDroptip.show()
                  g.nodeDropInParent = false
                }
                break
              } else if (g.nodeDropIn != -1) {
                g.nodeDropIn = -1
                g.nodeDropInParent = false
                g.nodeDroptip.hide()
                this.proxy.find('.l-drop-icon:first').removeClass('l-drop-yes  l-drop-add').addClass('l-drop-no')
              }
            }
          },
          onStopDrag: function (current, e) {
            var nodes = this.draggingNodes
            g.nodedragging = false
            if (g.nodeDropIn != -1) {
              for (var i = 0; i < nodes.length; i++) {
                var children = nodes[i].children
                if (children) {
                  nodes = $.grep(nodes, function (node, i) {
                    var isIn = $.inArray(node, children) == -1
                    return isIn
                  })
                }
              }
              for (var i in nodes) {
                var node = nodes[i]
                if (g.nodeDropInParent) {
                  g.remove(node)
                  g.append(g.nodeDropIn, [node])
                } else {
                  g.remove(node)
                  g.append(g.getParent(g.nodeDropIn), [node], g.nodeDropIn, g.nodeDropDir == 'bottom')
                }
              }
              g.nodeDropIn = -1
            }
            g.nodeDroptip.hide()
            this.set('cursor', 'default')
          }
        })
      }
    },
    // 递归设置父节点的状态
    _setParentCheckboxStatus: function (treeitem) {
      var g = this; var p = this.options
      // 当前同级别或低级别的节点是否都选中了
      var isCheckedComplete = $('.l-checkbox-unchecked', treeitem.parent()).length == 0
      // 当前同级别或低级别的节点是否都没有选中
      var isCheckedNull = $('.l-checkbox-checked', treeitem.parent()).length == 0

      if (isCheckedNull) {
        treeitem.parent().prev().find('> .l-checkbox')
          .removeClass('l-checkbox-checked l-checkbox-incomplete')
          .addClass('l-checkbox-unchecked')
      } else {
        if (isCheckedComplete || !p.enabledCompleteCheckbox) {
          treeitem.parent().prev().find('.l-checkbox')
            .removeClass('l-checkbox-unchecked l-checkbox-incomplete')
            .addClass('l-checkbox-checked')
        } else {
          treeitem.parent().prev().find('> .l-checkbox')
            .removeClass('l-checkbox-unchecked l-checkbox-checked')
            .addClass('l-checkbox-incomplete')
        }
      }
      if (treeitem.parent().parent('li').length > 0) { g._setParentCheckboxStatus(treeitem.parent().parent('li')) }
    }
  })

  function strTrim (str) {
    if (!str) return str
    return str.replace(/(^\s*)|(\s*$)/g, '')
  };
})(jQuery)
